package edu.thread.reentrantLock;

import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description: .
 * @Author: ZhaoWeiNan .
 * @CreatedTime: 2017/6/25 .
 * @Version: 1.0 .
 */
public class ReentrantLockTest extends Thread {

    private String type;

    //西瓜锁
    private ReentrantLock lock1;
    //西瓜刀锁
    private ReentrantLock lock2;
    //徒手吃西瓜锁
    private ReentrantLock lock3;

    public ReentrantLockTest(String type,String name,ReentrantLock lock1,ReentrantLock lock2){
        super(name);
        this.type = type;
        this.lock1 = lock1;
        this.lock2 = lock2;
    }

    public ReentrantLockTest(String type,String name,ReentrantLock lock3){
        super(name);
        this.type = type;
        this.lock3 = lock3;
    }

    @Override
    public void run() {
        if ("死锁".equals(type)){
            //死锁栗子
            DeadLock();
        }else if ("可重入".equals(type)){
            //可重入栗子
            ReentrantLock();
        }
    }

    /**
     *  一个阻塞的栗子。
     *  1.老公线程，先用西瓜加锁，拿到锁以后，再去用西瓜刀加锁。
     *  2.此时老婆线程已经获取到西瓜刀的锁，然后sleep了。
     *  3.老公线程获取不到西瓜刀的锁，所以被阻塞。
     */
    private void DeadLock(){
        if (Thread.currentThread().getName().equals("老公")){
            lock1.lock();
            System.out.println("老公买了西瓜，准备去拿西瓜刀。");
            lock2.lock();
            System.out.println("老公拿了西瓜刀，准备吃西瓜。");
            lock2.unlock();
            lock1.unlock();
        } else if (Thread.currentThread().getName().equals("老婆")){
            lock2.lock();
            System.out.println("老婆把西瓜刀藏起来了，不让老公吃西瓜。");
            try {
                Thread.sleep(1000000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock2.unlock();
        }
    }

    /**
     * 可重入的栗子。
     * 1.老公线程获取了徒手吃西瓜的锁，注意此时，徒手吃西瓜的锁并没有被释放。
     * 2.同时start了一个老婆线程了，徒手吃西瓜的锁并没有被释放，所以老婆线程没有获取到徒手吃西瓜锁。
     * 3.老公线程再次获取徒手吃西瓜的锁，没有被阻塞，证明了ReentrantLock的可重入。
     */
    private void ReentrantLock(){
        if (Thread.currentThread().getName().equals("老公")){
            lock3.lock();
            System.out.println("老公买了西瓜，徒手掰西瓜。");
            lock3.lock();
            System.out.println("老公掰开了西瓜，准备吃西瓜。");
            System.out.println("老公把老婆锁在外面，吃完西瓜才让她进来。");
            try {
                Thread.sleep(1000000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock3.unlock();
        }else if (Thread.currentThread().getName().equals("老婆")){
            System.out.println("老婆冲进家。");
            lock3.lock();
            System.out.println("老婆抓住老公的手，不让老公吃西瓜。");
            lock3.unlock();
        }


    }
}

class Demo1 {
    public static void main(String[] args){
        //先运行阻塞的栗子
       /* //西瓜锁
        ReentrantLock lock1 = new ReentrantLock();
        //西瓜刀锁
        ReentrantLock lock2 = new ReentrantLock();
        ReentrantLockTest lg = new ReentrantLockTest("死锁","老公",lock1,lock2);
        ReentrantLockTest lp = new ReentrantLockTest("死锁","老婆",lock1,lock2);

        lg.start();
        lp.start();*/

        //在运行可重入的栗子
        //徒手吃西瓜锁
        ReentrantLock lock3 = new ReentrantLock();
        ReentrantLockTest lg = new ReentrantLockTest("可重入","老公",lock3);
        ReentrantLockTest lp = new ReentrantLockTest("可重入","老婆",lock3);
        lg.start();
        lp.start();
    }
}
